package com.winhxd.b2c.admin.module.system.controller;

import com.winhxd.b2c.admin.common.context.UserManager;
import com.winhxd.b2c.admin.common.security.annotation.CheckPermission;
import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.constant.SysConstant;
import com.winhxd.b2c.common.domain.ResponseResult;
import com.winhxd.b2c.common.domain.system.security.enums.PermissionEnum;
import com.winhxd.b2c.common.domain.system.user.dto.SysUserLoginDTO;
import com.winhxd.b2c.common.domain.system.user.enums.UserStatusEnum;
import com.winhxd.b2c.common.domain.system.user.model.SysUser;
import com.winhxd.b2c.common.domain.system.user.vo.UserInfo;
import com.winhxd.b2c.common.feign.customer.CustomerServiceClient;
import com.winhxd.b2c.common.feign.system.UserServiceClient;
import com.winhxd.b2c.common.util.HttpClientUtil;
import com.winhxd.b2c.common.util.JsonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author zhangzhengyang
 * @description 登录管理
 * @date 2018/8/2
 */

@Api(tags = "登录管理")
@RestController
@RequestMapping("/")
public class LoginController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    private static final String MODULE_NAME = "登录管理";
    private static final String RETURN_NULL = "null";

    @Resource
    private Cache cache;
    @Resource
    private UserServiceClient userServiceClient;
    @Autowired
    private CustomerServiceClient customerServiceClient;
    @Autowired
    HttpClientUtil httpClientUtil;

    /**
     * 根据code获取openid的url
     */
//    @Value("${wechatLogin.config.url}")
//    private String openidUrl;
//    /**
//     * appid
//     */
//    @Value("${wechatLogin.config.appid}")
//    private String appid;
//    /**
//     * secret
//     */
//    @Value("${wechatLogin.config.secret}")
//    private String secret;
//    /**
//     * secret
//     */
//    @Value("${wechatLogin.config.grantTypeAuth}")
//    private String grantTypeAuth;






    @ApiOperation("登录")
    @ApiResponses({
            @ApiResponse(code = BusinessCode.CODE_OK, message = "成功"),
            @ApiResponse(code = BusinessCode.CODE_1001, message = "服务器内部异常"),
            @ApiResponse(code = BusinessCode.CODE_1004, message = "账号无效"),
            @ApiResponse(code = BusinessCode.CODE_1005, message = "密码错误"),
            @ApiResponse(code = BusinessCode.CODE_1006, message = "账号未启用"),
            @ApiResponse(code = BusinessCode.CODE_1007, message = "参数无效")
    })
    @PostMapping(value = "/login")
    public ResponseResult<Boolean> login(@RequestBody SysUserLoginDTO userLoginDTO, HttpServletRequest request, HttpServletResponse response) {
        logger.info("{} - 用户登录, 开始", MODULE_NAME);

        userLoginDTO.setPassword(DigestUtils.md5DigestAsHex(userLoginDTO.getPassword().getBytes()));

        ResponseResult<Boolean> result = new ResponseResult<>(BusinessCode.CODE_OK);

        if(StringUtils.isBlank(userLoginDTO.getAccount()) || StringUtils.isBlank(userLoginDTO.getPassword())){
            logger.info("{} - 参数无效，账号：{}", MODULE_NAME, userLoginDTO);
            result = new ResponseResult<>(BusinessCode.CODE_1007);
            result.setData(false);
            return result;
        }

        ResponseResult<SysUser> responseResult = userServiceClient.getByAccount(userLoginDTO.getAccount());
        if(responseResult.getCode() != BusinessCode.CODE_OK){
            logger.info("{} - {}，账号：{}", MODULE_NAME, responseResult.getMessage(), userLoginDTO);
            result = new ResponseResult<>(responseResult.getCode());
            result.setData(false);
            return result;
        }

        SysUser sysUser = responseResult.getData();
        if(null == sysUser){
            logger.info("{} - 登录账号无效，账号：{}", MODULE_NAME, userLoginDTO);
            result = new ResponseResult<>(BusinessCode.CODE_1004);
            result.setData(false);
            return result;
        }


        if(!sysUser.getPassword().equals(userLoginDTO.getPassword())){
            logger.info("{} - 登录密码错误，账号：{}", MODULE_NAME, userLoginDTO);
            result = new ResponseResult<>(BusinessCode.CODE_1005);
            result.setData(false);
            return result;
        }

        if(sysUser.getStatus().equals(UserStatusEnum.DISABLED.getCode())){
            logger.info("{} - 账号未启用，账号：{}", MODULE_NAME, userLoginDTO);
            result = new ResponseResult<>(BusinessCode.CODE_1006);
            result.setData(false);
            return result;
        }

        // 根据用户ID进行MD5加密生成Token
        String token = DigestUtils.md5DigestAsHex(sysUser.getId().toString().getBytes());
        logger.info("{} - 生成Token token={}", MODULE_NAME, token);
        String cacheKey = CacheName.CACHE_KEY_USER_TOKEN + token;
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(sysUser,userInfo);
        userInfo.setToken(token);
        logger.info("{} - 根据用户ID进行MD5加密生成Token", MODULE_NAME);

        //将token和用户信息放入缓存，并设置token过期时间为12个小时
        cache.setex(cacheKey,12 * 60 * 60, JsonUtil.toJSONString(userInfo));

        //将token写到客户端的cookie里面
        Cookie tokenCookie = null;
        Cookie[] requestCookies = request.getCookies();
        if(null != requestCookies){
            for(Cookie cookie : requestCookies){
                if(cookie.getName().equals(SysConstant.TOKEN_NAME)){
                    tokenCookie = cookie;
                }
            }
        }
        logger.info("{} - 将token和用户信息放入缓存，并设置token过期时间为12个小时, 将token写到客户端的cookie里面", MODULE_NAME);
        if(null == tokenCookie){
            tokenCookie = new Cookie(SysConstant.TOKEN_NAME, token);
        } else {
            tokenCookie.setValue(token);
        }
        // 设置为12小时
        tokenCookie.setMaxAge(12 * 60 * 60);
        tokenCookie.setPath("/");
        response.addCookie(tokenCookie);

        // 登录成功
        logger.info("{} - 用户登录成功, 账号={}", MODULE_NAME, userLoginDTO.getAccount());
        result.setData(true);
        return result;
    }



//    @ApiOperation("微信登录")
//    @ApiResponses({
//            @ApiResponse(code = BusinessCode.CODE_OK, message = "成功"),
//            @ApiResponse(code = BusinessCode.CODE_1001, message = "服务器内部异常"),
//            @ApiResponse(code = BusinessCode.CODE_1004, message = "账号无效"),
//            @ApiResponse(code = BusinessCode.CODE_1005, message = "密码错误"),
//            @ApiResponse(code = BusinessCode.CODE_1006, message = "账号未启用"),
//            @ApiResponse(code = BusinessCode.CODE_1007, message = "参数无效")
//    })
//    @PostMapping(value = "/wxLogin")
//    public ResponseResult<Boolean> wxLogin(@RequestBody SysUserLoginDTO userLoginDTO, HttpServletRequest request, HttpServletResponse response) {
//        String code = "abc";
//        logger.info("{} - 用户使用微信登录, 开始", MODULE_NAME);
//        logger.info("{} - code={}", MODULE_NAME, code);
//        ResponseResult<Boolean> result = new ResponseResult<>(BusinessCode.CODE_OK);
//        MiniOpenId miniOpenId = new MiniOpenId();
//        //请求参数
//        List<NameValuePair> params = new ArrayList<>();
//        params.add(new BasicNameValuePair("appid", appid));
//        params.add(new BasicNameValuePair("secret", secret));
//        params.add(new BasicNameValuePair("code", code));
//        params.add(new BasicNameValuePair("grant_type", grantTypeAuth));
//        try {
//            //发送请求
//            String data = httpClientUtil.doGet(openidUrl, params);
//            //解析相应内容（转换成json对象）
//            Map map = JsonUtil.parseJSONObject(data);
//            //错误码，成功的时候不会返回,获取到的是"null"(字符串null)，错误的时候返回错误码
//            String errcode = String.valueOf(map.get("errcode"));
//            if (RETURN_NULL.equals(errcode)){
//                //用户的唯一标识（openid）,获取不到的时候返回"null"(字符串null)
//                String openid =String.valueOf(map.get("openid"));
//                String sessionKey =String.valueOf(map.get("session_key"));
//                String unionId =String.valueOf(map.get("unionid"));
//                miniOpenId.setOpenid(openid);
//                miniOpenId.setSessionKey(sessionKey);
//                miniOpenId.setUnionid(unionId);
//                logger.info("用户使用微信登录 - [wxLogin] - 根据code获取openid,openid为={}",openid);
//            }else{
//                logger.error("用户使用微信登录 - [wxLogin] - 根据code获取openid出错，需查询错误码，错误码为={}",errcode);
//                result = new ResponseResult<>(BusinessCode.CODE_1001);
//                result.setData(false);
//                return result;
//            }
//            // 使用unionid 去customer_user表中查询用户信息
//            // TODO 异常错误码, 需要重新定义, 此查询用户接口还需要重新提供.
//            ResponseResult<PagedList<CustomerUserInfoVO>> info = customerServiceClient.queryCustomerPageInfo(new BackStageCustomerInfoCondition());
//            if(info.getCode() != BusinessCode.CODE_OK){
//                logger.error("用户使用微信登录 - [wxLogin] - 使用unionid 去customer_user表中查询用户信息 ,info.getCode()={}", info.getCode());
//                throw new BusinessException(BusinessCode.CODE_1001);
//            }
//            if(null == info.getData()){
//                logger.error("用户使用微信登录 - [wxLogin] - 使用unionid 去customer_user表中查询用户信息 ,info.getData()={}", info.getData());
//                throw new BusinessException(BusinessCode.CODE_1001);
//            }
//            if(null == info.getData().getData()){
//                logger.error("用户使用微信登录 - [wxLogin] - 使用unionid 去customer_user表中查询用户信息 ,info.getData().getData()={}", info.getData().getData());
//                throw new BusinessException(BusinessCode.CODE_1001);
//            }
//            // 按理来说这里应该只是有1个数据,
//            List<CustomerUserInfoVO> userList = info.getData().getData();
//            // 根据customer_id 获取sys_user信息
//            ResponseResult<SysUser> sysUserVO = userServiceClient.getSysUserById(1L);
//            if(sysUserVO.getCode() != BusinessCode.CODE_OK){
//                logger.error("用户使用微信登录 - [wxLogin] - 根据customer_id 获取sys_user表中查询用户信息 ,sysUser.getCode()={}", sysUserVO.getCode());
//                throw new BusinessException(BusinessCode.CODE_1001);
//            }
//            if(null == sysUserVO.getData()){
//                logger.error("用户使用微信登录 - [wxLogin] - 根据customer_id 获取sys_user表中查询用户信息 - 无权限登录 , sysUser.getData()={}", sysUserVO.getData());
//                throw new BusinessException(BusinessCode.CODE_1001);
//            }
//            // 原有逻辑不变
//            // 以下说明已经登录成功
//            // 根据用户ID进行MD5加密生成Token
//            SysUser sysUser = sysUserVO.getData();
//            String token = DigestUtils.md5DigestAsHex(sysUser.getId().toString().getBytes());
//            String cacheKey = CacheName.CACHE_KEY_USER_TOKEN + token;
//            UserInfo userInfo = new UserInfo();
//            BeanUtils.copyProperties(sysUser,userInfo);
//            userInfo.setToken(token);
//
//            //将token和用户信息放入缓存，并设置token过期时间为12个小时
//            cache.setex(cacheKey,12 * 60 * 60, JsonUtil.toJSONString(userInfo));
//
//            //将token写到客户端的cookie里面
//            Cookie tokenCookie = null;
//            Cookie[] requestCookies = request.getCookies();
//            if(null != requestCookies){
//                for(Cookie cookie : requestCookies){
//                    if(cookie.getName().equals(SysConstant.TOKEN_NAME)){
//                        tokenCookie = cookie;
//                    }
//                }
//            }
//            if(null == tokenCookie){
//                tokenCookie = new Cookie(SysConstant.TOKEN_NAME, token);
//            } else {
//                tokenCookie.setValue(token);
//            }
//            // 设置为12小时
//            tokenCookie.setMaxAge(12 * 60 * 60);
//            tokenCookie.setPath("/");
//            response.addCookie(tokenCookie);
//
//            // 登录成功
//            logger.info("{} - 用户登录成功, 账号={}", MODULE_NAME, userLoginDTO.getAccount());
//            result.setData(true);
//            return result;
//
//        } catch (IOException e) {
//            logger.error("用户使用微信登录 - [wxLogin] - 根据code获取openid出错，异常信息为={}",e);
//            result = new ResponseResult<>(BusinessCode.CODE_1001);
//            result.setData(false);
//            return result;
//        } catch (URISyntaxException e) {
//            logger.error("用户使用微信登录 - [wxLogin] - 根据code获取openid出错，异常信息为={}",e);
//            result = new ResponseResult<>(BusinessCode.CODE_1001);
//            result.setData(false);
//            return result;
//        } catch (Exception e){
//            logger.error("用户使用微信登录 - [wxLogin] - 根据code获取openid出错，异常信息为={}",e);
//            result = new ResponseResult<>(BusinessCode.CODE_1001);
//            result.setData(false);
//            return result;
//        }
//
//    }





    @ApiOperation("注销")
    @ApiResponses({
            @ApiResponse(code = BusinessCode.CODE_OK, message = "成功"),
            @ApiResponse(code = BusinessCode.CODE_1001, message = "服务器内部异常")
    })
    @GetMapping(value = "/logout")
    @CheckPermission(PermissionEnum.AUTHENTICATED)
    public ResponseResult<Boolean> login(HttpServletRequest request, HttpServletResponse response) {
        UserInfo userInfo = UserManager.getCurrentUser();
        logger.info("{} - 用户注销, 参数：userInfo={}", MODULE_NAME, userInfo);

        ResponseResult<Boolean> result = new ResponseResult<>(BusinessCode.CODE_OK);

        //获取客户端的cookie数据
        Cookie[] requestCookies = request.getCookies();
        if(null != requestCookies){
            for(Cookie cookie : requestCookies){
                if(cookie.getName().equals(SysConstant.TOKEN_NAME)){
                    String token = cookie.getValue();
                    String cacheKey = CacheName.CACHE_KEY_USER_TOKEN + token;

                    //删除缓存里面的token和用户信息
                    cache.del(cacheKey);

                    //删除客户端的cookie里面的token
                    cookie.setValue(null);
                    cookie.setMaxAge(0);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
        }
        // 注销成功
        logger.info("{} - 用户注销成功, 参数：userInfo={}", MODULE_NAME, userInfo);
        result.setData(true);
        return result;
    }
}
